package com.liufei.class02;

public class Code02_RandToRand {


    public static void main(String[] args) {
        int times = 10000000;
        int count = 0;
        for (int i = 0; i < times; i++) {
            if (Math.random() < 0.5) {
                count++;
            }
        }
        System.out.println((double) count / times);

        System.out.println("===================");

        // [0, 1) -> [0, 8)
        count = 0;
        for (int i = 0; i < times; i++) {
            if (Math.random() * 8 < 5) {
                count++;
            }
        }
        System.out.println((double) count / times);
        System.out.println((double) 5 / 8);

        int k = 9;
        // [0, k) -> [0, k - 1]
        int[] counts = new int[9];
        for (int i = 0; i < times; i++) {
            int ans = (int) (Math.random() * k);
            counts[ans]++;
        }
        for (int i = 0; i < k; i++) {
            System.out.println(i + "这个数，出现了 " + counts[i] + " 次");
        }
        System.out.println("=========");

        // 验证
        count = 0;
        double x = 0.4;
        for (int i = 0; i < times; i++) {
            if (xToXPower2() < x) {
                count++;
            }
        }
        System.out.println((double) count / times);
        System.out.println(Math.pow(x, 2));
        System.out.println("=========");

        // 验证
        count = 0;
        for (int i = 0; i < times; i++) {
            if (xToXPower3() < x) {
                count++;
            }
        }
        System.out.println((double) count / times);
        System.out.println(Math.pow(x, 3));

        System.out.println("=========");

        // 验证
        int[] counts2 = new int[8];
        for (int i = 0; i < times; i++) {
            counts2[f3_2()]++;
        }
        for (int i = 0; i < counts2.length; i++) {
            System.out.println(i + "这个数，出现了 " + counts2[i] + " 次");
        }
        System.out.println("=========");

        // 验证
        count = 0;
        for (int i = 0; i < times; i++) {
            if (g1() == 1) {
                count++;
            }
        }
        System.out.println((double) count / times);
    }


    // 如果利用Math.random()函数，
    // 把得到[0,x)范围上的数的概率从x调整成x^2
    public static double xToXPower2() {
        return Math.max(Math.random(), Math.random());
    }

    // 如果利用Math.random()函数，
    // 把得到[0,x)范围上的数的概率从x调整成x^2
    public static double xToXPower2_min() {
        return Math.min(Math.random(), Math.random());
    }

    // 如果利用Math.random()函数，
    // 把得到[0,x)范围上的数的概率从x调整成x^3
    public static double xToXPower3() {
        return Math.max(Math.random(), Math.max(Math.random(), Math.random()));
    }

    // 相当于系统函数，不等修改
    public static int f() {
        return (int)(Math.random() * 5 + 1);
    }

    // 等概率返回0和1
    public static int f1() {
        int ans = 0;
        do {
            ans = f();
        } while (ans == 3); // 重试，继续调用f(x)
        return ans < 3 ? 0 : 1;
    }

    // 等概率返回0 ～ 7 之间的整数
    public static int f2() {
        // 或者 return (f1() << 2) + (f1() << 1) + f1();
        return (f1() << 2) + (f1() << 1) + (f1() << 0);
    }

    // 等概率返回 0 ～ 6 之间的整数, 跟f1(x)方式一样，结果等于7的时候，继续调用f2(x)
    public static int f3() {
        int ans = 0;
        do {
            ans = f2();
        } while (ans == 7); // 重试，继续调用f2(x)
        return ans;
    }

    // 等概率返回 1 ～ 7 之间的整数, 跟f1(x)方式一样，结果等于0的时候，继续调用f2(x)
    public static int f3_2() {
        int ans = 0;
        do {
            ans = f2();
        } while (ans == 0); // 重试，继续调用f2(x)
        return ans;
    }

    public static int g() {
        // f3的范围是等概率返回 [0, 6] 之间的整数
        // 加上1之后就是等概率返回 [1, 7] 之间的整数了
        return f3() + 1;
    }

    // 随机不等概率的返回0和1，相当于系统函数，无法修改
    public static int x() {
        return Math.random() < 0.7 ? 0 : 1;
    }

    public static int g1() {
        int ans = 0;
        do {
            ans = x();
        } while (ans == x());
        return ans;
    }
}
